#include "soc_gpio.h"


#define UNPACK_PORT_PIN(portPin) (portPin >> 8) & 0xff, portPin & 0xff

void SOC_GpioInit(SOC_GpioPort_t port, int pin, SOC_GpioMode_t mode)
{
   UNUSED(port);
   UNUSED(pin);
   UNUSED(mode);
}

void SOC_GpioWrite(SOC_GpioPort_t port, int pin, int val)
{
#define SET_PORT_BIT(p) \
    if(val == 0) \
        p &= ~(0x01 << pin); \
    else \
        p |= (0x01 << pin)

    switch(port)
    {
        case S_P0:
            SET_PORT_BIT(P0);
        break;
        case S_P1:
            SET_PORT_BIT(P1);
        break;
        case S_P2:
            SET_PORT_BIT(P2);
        break;
        case S_P3:
            SET_PORT_BIT(P3);
        break;
    }

#undef SET_PORT_BIT
}

void SOC_GpioTrigger(SOC_GpioPort_t port, int pin)
{
    switch(port)
    {
        case S_P0:
            P0 ^= (0x01 << pin);
        break;
        case S_P1:
            P1 ^= (0x01 << pin);
        break;
        case S_P2:
            P2 ^= (0x01 << pin);
        break;
        case S_P3:
            P3 ^= (0x01 << pin);
        break;
    }
}

int SOC_GpioRead(SOC_GpioPort_t port, int pin)
{
    switch(port)
    {
        case S_P0:
            return (P0 & (0x01 << pin)) != 0;
        break;
        case S_P1:
            return (P1 & (0x01 << pin)) != 0;
        break;
        case S_P2:
            return (P2 & (0x01 << pin)) != 0;
        break;
        case S_P3:
            return (P3 & (0x01 << pin)) != 0;
        break;
    }

    return 0;
}

void SOC_GpioSetItMode(SOC_GpioPort_t port, int pin, SOC_GpioItMode_t mode)
{
    int tModeFlag = 0;

    if(port != S_P3)
        return;
    
    if(mode == S_GPIO_IT_FALLING)
    {
        tModeFlag = 1;
    } 
    else if(mode == S_GPIO_IT_LowLevel)
    {
        tModeFlag = 0;
    }
    else 
    {
        return;
    }
    
    if(pin == 2)
    {
        OP_BIT(TCON, 0, tModeFlag);
    }
    else if(pin == 3)
    {
        OP_BIT(TCON, 2, tModeFlag);
    }
}

void SOC_GpioSet_IT(SOC_GpioPort_t port, int pin, bool en)
{
    if(port != S_P3)
        return;
    
    if(pin == 2)
    {
        OP_BIT(IE, 0, en);
    }
    else if(pin == 3)
    {
        OP_BIT(IE, 2, en);
    }
}

void SOC_GpioInitExt(uint16_t portPin, SOC_GpioMode_t mode)
{
    SOC_GpioInit(UNPACK_PORT_PIN(portPin), mode);
}

void SOC_GpioWriteExt(uint16_t portPin, int val)
{
    SOC_GpioWrite(UNPACK_PORT_PIN(portPin), val);
}

void SOC_GpioTriggerExt(uint16_t portPin)
{
    SOC_GpioTrigger(UNPACK_PORT_PIN(portPin));
}

int SOC_GpioReadExt(uint16_t portPin)
{
    return SOC_GpioRead(UNPACK_PORT_PIN(portPin));
}

void SOC_GpioSetItModeExt(uint16_t portPin, SOC_GpioItMode_t mode)
{
    SOC_GpioSetItMode(UNPACK_PORT_PIN(portPin), mode);
}

void SOC_GpioSet_ITExt(uint16_t portPin, bool en)
{
    SOC_GpioSet_IT(UNPACK_PORT_PIN(portPin), en);
}
